/**
 * Created with JetBrains PhpStorm.
 * User: ishowshao
 * Date: 13-3-7
 * Time: 下午3:42
 */
(function (namespace, name) {
    var makeOptions = function (optionData) {
        var el = jQuery('<div class="i-combo-box-options"></div>');
        for (var i = 0; i < optionData.length; i++) {
            el.append('<div class="i-combo-box-option" data-value="' + optionData[i]['value'] + '" data-display="' + optionData[i]['display'] + '" data-id="' + optionData[i]['__id__'] + '"><span class="i-combo-box-option-text">' + optionData[i]['display'] + '</span></div>');
        }
        return el;
    };
    var getDisplayByValue = function (data, value) {
        var display = value;
        for (var i = 0; i < data.length; i++) {
            if (value === data[i]['value']) {
                display = data[i]['display'];
                break;
            }
        }
        return display;
    };
    var filter = function (source, value, key, exactMatch, caseSensitive) {
        var result = [];
        key = key || 'display';
        for (var i = 0; i < source.length; i++) {
            if (typeof source[i][key] != 'undefined') {
                if (exactMatch) {
                    if (value === source[i][key] || value === '') {
                        result.push(source[i]);
                    }
                } else {
                    //构建正则对象
                    var reg = new RegExp(value, caseSensitive ? 'i' : '');
                    if (reg.test(source[i][key])) {
                        result.push(source[i]);
                    }
                }
            }
        }
        return result;
    };
    var initData = function (data) {
        var result = [];
        if (Object.prototype.toString.call(data) == '[object Array]') {
            for (var i = 0; i < data.length; i++) {
                data[i]['__id__'] = i;
                result.push(data[i]);
            }
        }
        return result;
    };
    var getRecordById = function (data, id) {
        return getRecordByKey(data, '__id__', id);
    };
    var getRecordByKey = function (data, key, value) {
        var record = {};
        for (var i = 0; i < data.length; i++) {
            if (data[i][key] === value) {
                record = data[i];
                break;
            }
        }
        return record;
    };
    var ComboBox = function (config) {
        this.config = config || {};
        this.data = initData(this.config.data);
        this.value = this.config.value || '';
        this.recordId = 0;
        this.filteredData = this.data;
        this.filter = this.config.filter || {};
        this.selectedIndex = -1;
        this.make();
    };
    ComboBox.prototype = {
        make: function () {
            var that = this;
            this.el = jQuery('<div class="i-combo-box-input-ct"><input class="i-combo-box-input" type="text"><input class="i-combo-box-hidden" type="hidden"><span class="i-combo-box-trigger"><em></em></span></div>');
            this.hiddenEl = this.el.children('.i-combo-box-hidden');
            this.inputEl = this.el.children('.i-combo-box-input');
            this.triggerEl = this.el.children('.i-combo-box-trigger');
            this.inputEl.val(getDisplayByValue(this.data, this.value));

            this.hiddenEl.attr('name', this.config.name || '').val(this.value);
            this.inputEl.click(function () {
                that.mouseOverOptions = false;
                that.filteredData = that.data;
                ComboBox.prototype.expand.call(that);
            });
            this.triggerEl.click(function () {
                that.filteredData = that.data;
                that.inputEl.focus();
                ComboBox.prototype.expand.call(that);
            });
            this.inputEl.blur(function () {
                if (!that.mouseOverOptions) {
                    ComboBox.prototype.collapse.call(that);
                }
            });

            this.inputEl.keyup(function (e) {
                if (e.which == 40) {
                    //down
                    if (that.selectedIndex < that.filteredData.length - 1) {
                        that.selectedIndex++;
                        that.optionEl && that.optionEl.find('.i-combo-box-option').removeClass('i-combo-box-option-selected').eq(that.selectedIndex).addClass('i-combo-box-option-selected');
                    }
                } else if (e.which == 38) {
                    //up
                    if (that.selectedIndex > 0) {
                        that.selectedIndex--;
                        that.optionEl && that.optionEl.find('.i-combo-box-option').removeClass('i-combo-box-option-selected').eq(that.selectedIndex).addClass('i-combo-box-option-selected');
                    }
                } else if (e.which == 13) {
                    //enter
                    that.optionEl && that.selectedIndex != -1 && that.optionEl.find('.i-combo-box-option:eq(' + that.selectedIndex + ')').click();
                    e.preventDefault();
                } else {
                    that.filteredData = filter(that.data, jQuery(this).val(), that.filter['key'] || 'display', that.filter['exactMatch'], that.filter['caseSensitive']);
                    that.collapse();
                    that.expand();
                    that.selectedIndex = -1;
                }
            });

            //input中按回车，会导致表单提交，要避免表单提交
            this.inputEl.keydown(function (e) {
                if (e.which == 13) {
                    e.preventDefault();
                }
            });
        },
        expand: function () {
            if (!this.optionEl) {
                var that = this;
                this.optionEl = makeOptions(this.filteredData);

                var inputOffset = this.el.offset();
                jQuery('body').append(this.optionEl.width(this.el.outerWidth() - 2));
                this.optionEl.offset({
                    top: inputOffset.top + this.el.outerHeight(),
                    left: inputOffset.left
                });

                this.optionEl.delegate('.i-combo-box-option', 'click', function () {
                    that.hiddenEl.val(jQuery(this).data('value'));
                    that.inputEl.val(jQuery(this).data('display'));
                    var id = Number(jQuery(this).data('id'));
                    console.log(getRecordById(that.data, id));
                    that.collapse();
                    that.inputEl.focus();
                });
                this.optionEl.bind('mouseover', function () {
                    that.mouseOverOptions = true;
                });
                this.optionEl.bind('mouseout', function () {
                    that.mouseOverOptions = false;
                });

//                this.optionEl.find('.i-combo-box-option').eq(that.selectedIndex).addClass('i-combo-box-option-selected');
            }
        },
        collapse: function () {
            if (this.optionEl) {
                this.optionEl.remove();
                delete this.optionEl;
            }
        },
        render: function (renderTo) {
            jQuery(renderTo).append(this.el);
        },
        getValue: function () {
            return this.value;
        },
        setValue: function (value) {
            this.value = value;
            this.inputEl.val(getDisplayByValue(this.data, value));
            this.hiddenEl.val(value);
        },
        setParent: function (combo) {
            this.parent = combo;
            this.parent.onChange(function () {

            });
        },
        onChange: function (listener) {
            if (typeof listener == 'function') {
                listener.call(this, this.value);
            }
        }
    };
    ComboBox.prototype.constructor = ComboBox;

    namespace = namespace || window;
    name = name || 'ComboBox';

    namespace[name] = ComboBox;
})(window, 'ComboBox');
